﻿package jlib.component.scroll
{
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import jlib.core.geom.Vector2D;
	
	public class ScrollTrackManager extends EventDispatcher
	{
		protected var m_stage:Stage;
		protected var m_target:DisplayObject;
		protected var m_track:DisplayObject;
		protected var m_thumb:InteractiveObject;
		
		protected var m_movableLine:Vector2D;
		protected var m_downPosition:Point;
		
		protected var m_currentPosition:Number;
		protected var m_interactiveable:Boolean;
		protected var m_thumbDownDistance:Number;
		
		protected var m_scrollbar:ScrollBar;
		
		protected var m_isDisposed:Boolean;
		
		public function ScrollTrackManager($scrollbar:ScrollBar)
		{
			m_scrollbar = $scrollbar;
			init();
		}
		
		private function init(): void
		{
			m_interactiveable = true;
			m_currentPosition = 0;
			m_downPosition = new Point();
			m_movableLine = new Vector2D(new Point(), new Point());
		}
		
		public function getInteractiveable(): Boolean { return m_interactiveable; }
		public function setInteractiveable($boolean:Boolean=true): void
		{
			m_interactiveable = $boolean;
			update();
		}
		
		public function getPosition(): Number { return m_currentPosition; }
		public function setPosition(rate:Number): void 
		{
			const MAX:Number = 0.98;
			const MIN:Number = 0.01;
			if(rate < MIN) rate = 0;
			if(rate > MAX) rate = 1;
			
			var targetPosition:Point = m_movableLine.getPosition(rate);
			m_thumb.x = targetPosition.x;
			m_thumb.y = targetPosition.y;
			
			updateCurrentPosition();
			
			if(m_currentPosition < MIN) m_currentPosition = 0;
			if(m_currentPosition > MAX) m_currentPosition = 1;
			if(m_currentPosition >= 1) m_currentPosition = 1;
			if(isNaN(m_currentPosition)) m_currentPosition = 0;
			if(!isFinite(m_currentPosition)) m_currentPosition = 0;
			
			this.dispatchEvent(new Event(Event.CHANGE));
		}
		
		// thumb 인터렉티브 부여
		private function switchInteractive(e:Event=null): void
		{
			if(!m_thumb.stage){
				m_thumb.addEventListener(Event.ADDED_TO_STAGE, switchInteractive ); 
				return;	
			}
			m_stage = m_thumb.stage;
			if(m_stage) m_thumb.removeEventListener(Event.ADDED_TO_STAGE, switchInteractive);
			if(m_isDisposed) {
				dispose();
				return ;
			}
			if(m_interactiveable) {
				m_thumb.addEventListener(MouseEvent.MOUSE_DOWN, mouseListener );
				m_stage.addEventListener(MouseEvent.CLICK, onTrackClick );
			}else{
				m_thumb.removeEventListener(MouseEvent.MOUSE_DOWN, mouseListener );
				m_stage.removeEventListener(MouseEvent.CLICK, onTrackClick );
			} 
		}
		
		private function mouseListener(e:MouseEvent): void
		{
			switch(e.type){
				case MouseEvent.MOUSE_DOWN :
					m_downPosition.x = m_stage.mouseX;
					m_downPosition.y = m_stage.mouseY;
					m_thumbDownDistance = getPosition();
					m_stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseListener);
					m_stage.addEventListener(MouseEvent.MOUSE_UP, mouseListener);
				break;
				case MouseEvent.MOUSE_MOVE :
					onThumbMove(e);
				break;
				case MouseEvent.MOUSE_UP :
					m_stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseListener );
					m_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseListener );
				break;
			}
		}
		
		public function update(e:Event=null): void
		{
			m_thumb = m_scrollbar.getThumb();
			m_track = m_scrollbar.getTrack();
			m_target = m_scrollbar.getTarget();
			if(!m_track||!m_thumb) return ;
			
			switchInteractive();
			updateMovableLine();
			setPosition(m_currentPosition);
		}
		
		public function isMaxPosition(): Boolean { return (getPosition() == 1); }
		
		public function isMinPosition(): Boolean { return (getPosition() == 0); }
		
		protected function onThumbMove(e:Event): void { throw new Error("templete method"); }
		
		protected function onTrackClick(e:Event): void { throw new Error("templete method"); }
		
		protected function updateMovableLine(): void { throw new Error("templete method"); }
		
		protected function updateCurrentPosition(): void { throw new Error("templete method"); }
		
		public function dispose(): void
		{
			if(m_thumb) m_thumb.removeEventListener(MouseEvent.MOUSE_DOWN, mouseListener );
			if(m_stage) {
				m_stage.removeEventListener(MouseEvent.CLICK, onTrackClick );
				m_downPosition = null;
				m_movableLine = null;
				m_scrollbar = null;
				m_track = m_thumb = m_stage = null;
			}
			m_isDisposed = true;
		}
		
	}//c
}